<!DOCTYPE html>
<html>

<head>
  <title>cannon.js - stacks demo</title>
  <meta charset="utf-8">
  <link rel="stylesheet" href="css/style.css" type="text/css" />
  <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>

<body>
  <script src="../../feng3d/out/feng3d.js"></script>
  <script src="../out/cannon.js"></script>
  <script src="../build/cannon.demo.js"></script>
  <script src="../libs/dat.gui.js"></script>
  <script src="../libs/Three.js"></script>
  <script src="../libs/TrackballControls.js"></script>
  <script src="../libs/Detector.js"></script>
  <script src="../libs/Stats.js"></script>
  <script src="../libs/smoothie.js"></script>
  <script>

    /**
     * For debugging different kinds of stacks
     */
    var demo = new CANNON.Demo();
    var size = 2, mass = 5;

    function createTetra()
    {
      var verts = [new CANNON.Vector3(0, 0, 0),
      new CANNON.Vector3(2, 0, 0),
      new CANNON.Vector3(0, 2, 0),
      new CANNON.Vector3(0, 0, 2)];
      var offset = -0.35;
      for (var i = 0; i < verts.length; i++)
      {
        var v = verts[i];
        v.x += offset;
        v.y += offset;
        v.z += offset;
      }
      return new CANNON.ConvexPolyhedron(verts,
        [
          [0, 3, 2], // -x
          [0, 1, 3], // -y
          [0, 2, 1], // -z
          [1, 2, 3], // +xyz
        ]);
    }
    function createBoxPolyhedron(size)
    {
      size = size || 1;
      var box = new CANNON.Box(new CANNON.Vector3(size, size, size));
      return box.convexPolyhedronRepresentation;
    }

    function createCompound(mass)
    {
      var compoundBody = new CANNON.Body({ mass: mass });
      var s = size;
      var shape = new CANNON.Box(new CANNON.Vector3(0.5 * s, 0.5 * s, 0.5 * s));
      compoundBody.addShape(shape, new CANNON.Vector3(0, 0, s));
      compoundBody.addShape(shape, new CANNON.Vector3(0, 0, 0));
      compoundBody.addShape(shape, new CANNON.Vector3(0, 0, -s));
      compoundBody.addShape(shape, new CANNON.Vector3(-s, 0, -s));
      return compoundBody;
    }

    // Spheres
    demo.addScene("sphere/sphere", function ()
    {
      var world = setupWorld(demo);

      // Sphere 1
      var sphereShape = new CANNON.Sphere(size);
      var b1 = new CANNON.Body({ mass: 5 });
      b1.addShape(sphereShape);
      b1.position.set(0, 0, 3 * size);
      world.addBody(b1);
      demo.addVisual(b1);

      // Sphere 2
      var b2 = new CANNON.Body({ mass: 5 });
      b2.addShape(sphereShape);
      b2.position.set(0, 0, 1 * size);
      world.addBody(b2);
      demo.addVisual(b2);
    });

    // Sphere/plane
    demo.addScene("sphere/plane", function ()
    {
      var world = setupWorld(demo);

      // Sphere 1
      var sphereShape = new CANNON.Sphere(size);
      var b1 = new CANNON.Body({ mass: 5 });
      b1.addShape(sphereShape);
      b1.position.set(0, 0, 3 * size);
      world.addBody(b1);
      demo.addVisual(b1);
    });

    // Sphere / box side
    demo.addScene("sphere/box", function ()
    {
      var world = setupWorld(demo);

      var boxShape = new CANNON.Box(new CANNON.Vector3(size, size, size));
      var sphereShape = new CANNON.Sphere(size);

      // Box
      var b1 = new CANNON.Body({ mass: 5 });
      b1.addShape(boxShape);
      b1.position.set(0, 0, 1 * size);
      world.addBody(b1);
      demo.addVisual(b1);

      // Sphere
      var b2 = new CANNON.Body({ mass: 5 });
      b2.addShape(sphereShape);
      b2.position.set(0, 0, 3 * size);
      world.addBody(b2);
      demo.addVisual(b2);
    });

    demo.addScene("sphere/compound", function ()
    {
      var world = setupWorld(demo);

      // Sphere
      var sphereShape = new CANNON.Sphere(size * 0.5);
      var b = new CANNON.Body({ mass: 5 });
      b.addShape(sphereShape);
      b.position.set(-size, 0, 6 * size);
      world.addBody(b);
      demo.addVisual(b);

      var compoundBody = createCompound(mass);
      compoundBody.position.set(0, 0, size * 3);
      world.addBody(compoundBody);
      demo.addVisual(compoundBody);
    });

    demo.addScene("sphere/convex", function ()
    {
      var world = setupWorld(demo);

      // Sphere
      var sphereShape = new CANNON.Sphere(size * 0.5);
      var b = new CANNON.Body({ mass: 5 });
      b.addShape(sphereShape);
      b.position.set(0, 0, 6 * size);
      world.addBody(b);
      demo.addVisual(b);

      var shape = createTetra();//createBoxPolyhedron(size);
      var b1 = new CANNON.Body({ mass: 5 });
      b1.addShape(shape);
      b1.position.set(0, 0, 1 * size);
      world.addBody(b1);
      demo.addVisual(b1);
    });

    demo.addScene("sphere/particle", function ()
    {
      var world = setupWorld(demo);

      // Sphere
      var sphereShape = new CANNON.Sphere(size * 0.5);
      var b = new CANNON.Body({ mass: 5 });
      b.addShape(sphereShape);
      b.position.set(0, 0, size);
      world.addBody(b);
      demo.addVisual(b);

      // Particle
      var p = new CANNON.Body({ mass: 1 });
      p.addShape(new CANNON.Particle());
      p.position.set(0.02, 0, 3 * size);

      world.addBody(p);
      demo.addVisual(p);
    });

    demo.addScene("plane/box", function ()
    {
      var world = setupWorld(demo);
      var boxShape = new CANNON.Box(new CANNON.Vector3(size, size, size));
      var b1 = new CANNON.Body({ mass: 5 });
      b1.addShape(boxShape);
      b1.position.set(0, 0, 1 * size);
      world.addBody(b1);
      demo.addVisual(b1);
    });

    demo.addScene("plane/compound", function ()
    {
      var world = setupWorld(demo);
      var b1 = createCompound(5);
      b1.position.set(0, 0, 4 * size);
      world.addBody(b1);
      demo.addVisual(b1);
    });

    demo.addScene("plane/convex", function ()
    {
      var world = setupWorld(demo);
      var shape = createTetra();
      var b1 = new CANNON.Body({ mass: 5 });
      b1.addShape(shape);
      b1.position.set(0, 0, 1 * size);
      world.addBody(b1);
      demo.addVisual(b1);
    });

    demo.addScene("plane/particle", function ()
    {
      var world = setupWorld(demo);
      // Particle
      var p = new CANNON.Body({ mass: 1 });
      p.addShape(new CANNON.Particle());
      p.position.set(0.02, 0, 3 * size);
      world.addBody(p);
      demo.addVisual(p);
    });

    // Boxes
    demo.addScene("box/box", function ()
    {
      var world = setupWorld(demo);

      // Box 1
      var boxShape = new CANNON.Box(new CANNON.Vector3(size * 0.5, size * 0.5, size * 0.5));
      var b1 = new CANNON.Body({ mass: 5 });
      b1.addShape(boxShape);
      b1.position.set(0, 0, 1 * size);
      world.addBody(b1);
      demo.addVisual(b1);

      // Box 2
      var b2 = new CANNON.Body({ mass: 5 });
      b2.addShape(boxShape);
      b2.position.set(size * 0.5, 0, 3 * size);
      world.addBody(b2);
      demo.addVisual(b2);
    });

    demo.addScene("box/compound", function ()
    {
      var world = setupWorld(demo);

      var b2 = createCompound(5);
      b2.position.set(size * 0.5, 0, 2 * size);
      world.addBody(b2);
      demo.addVisual(b2);

      var boxShape = new CANNON.Box(new CANNON.Vector3(size * 0.5, size * 0.5, size * 0.5));
      var b1 = new CANNON.Body({ mass: 5 });
      b1.addShape(boxShape);
      b1.position.set(0, 0, 7 * size);
      world.addBody(b1);
      demo.addVisual(b1);
    });

    demo.addScene("box/convex", function ()
    {
      var world = setupWorld(demo);

      var shape = createTetra(size);
      var b2 = new CANNON.Body({ mass: 5 });
      b2.addShape(shape);
      b2.position.set(0, 0, 5 * size);
      world.addBody(b2);
      demo.addVisual(b2);

      var boxShape = new CANNON.Box(new CANNON.Vector3(size * 0.5, size * 0.5, size * 0.5));
      var b1 = new CANNON.Body({ mass: 5 });
      b1.addShape(boxShape);
      b1.position.set(0, 0, 2 * size);
      world.addBody(b1);
      demo.addVisual(b1);
    });

    demo.addScene("box/particle", function ()
    {
      var world = setupWorld(demo);

      var boxShape = new CANNON.Box(new CANNON.Vector3(size * 0.5, size * 0.5, size * 0.5));
      var b1 = new CANNON.Body({ mass: 5 });
      b1.addShape(boxShape);
      b1.position.set(0, 0, 1 * size);
      world.addBody(b1);
      demo.addVisual(b1)

      // Particle
      var p = new CANNON.Body({ mass: 1 });
      p.addShape(new CANNON.Particle());
      p.position.set(0, 0, 3 * size);
      world.addBody(p);
      demo.addVisual(p);
    });

    demo.addScene("compound/compound", function ()
    {
      var world = setupWorld(demo);

      var b2 = createCompound(5);
      b2.position.set(size * 0.5, 0, 6 * size);
      world.addBody(b2);
      demo.addVisual(b2);

      var b2 = createCompound(5);
      b2.position.set(size * 0.5, 0, 2 * size);
      world.addBody(b2);
      demo.addVisual(b2);
    });

    demo.addScene("compound/convex", function ()
    {
      var world = setupWorld(demo);

      var tetraShape = createTetra();

      var b1 = new CANNON.Body({ mass: 5 });
      b1.addShape(tetraShape);
      b1.position.set(0, 0, 3 * size);
      world.addBody(b1);
      demo.addVisual(b1);

      // Box 2
      var boxShape = new CANNON.Box(new CANNON.Vector3(size * 0.5, size * 0.5, size * 0.5));
      var b2 = new CANNON.Body({ mass: 5 });
      b2.addShape(boxShape);
      b2.position.set(0, 0, 1 * size);
      world.addBody(b2);
      demo.addVisual(b2);
    });

    demo.addScene("compound/particle", function ()
    {
      var world = setupWorld(demo);

      var t = createCompound(5);
      t.position.set(0, 0, 4 * size);

      // Particle
      var p = new CANNON.Body({ mass: 1 });
      p.addShape(new CANNON.Particle());
      p.position.set(0, 0, 7 * size);
      world.addBody(t);
      demo.addVisual(t);
      world.addBody(p);
      demo.addVisual(p);
    });

    // ConvexPolyhedron and box
    demo.addScene("convex/convex", function ()
    {
      var world = setupWorld(demo);

      var tetraShape = createTetra();
      var b1 = new CANNON.Body({ mass: 5 });
      b1.addShape(tetraShape);
      b1.position.set(0.1, 0.1, 5 * size);
      world.addBody(b1);
      demo.addVisual(b1);

      var tetraShape = createTetra();
      var b1 = new CANNON.Body({ mass: 5 });
      b1.addShape(tetraShape);
      b1.position.set(0, 0, 3 * size);
      world.addBody(b1);
      demo.addVisual(b1);

    });

    // ConvexPolyhedron and particle
    demo.addScene("convex/particle", function ()
    {
      var world = setupWorld(demo);

      var tetraShape = createBoxPolyhedron(size);
      var t = new CANNON.Body({ mass: 5 });
      t.addShape(tetraShape);
      t.position.set(0, 0, 1 * size);
      t.quaternion.fromAxisAngle(new CANNON.Vector3(1, 0, 0), Math.PI / 2);

      // Particle
      var p = new CANNON.Body({ mass: 1 });
      p.addShape(new CANNON.Particle());
      p.position.set(0, 0, 3 * size);

      world.addBody(t);
      demo.addVisual(t);
      world.addBody(p);
      demo.addVisual(p);
    });

    demo.start();

    function setupWorld(demo)
    {
      var world = demo.getWorld();
      world.gravity.set(0, 0, -10);
      world.broadphase = new CANNON.NaiveBroadphase();
      world.solver.iterations = 20;

      world.defaultContactMaterial.contactEquationStiffness = 1e7;
      world.defaultContactMaterial.contactEquationRelaxation = 5;

      // ground plane
      var groundShape = new CANNON.Plane();
      var groundBody = new CANNON.Body({ mass: 0 });
      groundBody.addShape(groundShape);
      groundBody.position.set(0, 0, -1);
      //groundBody.quaternion.fromAxisAngle(new CANNON.Vector3(0,1,0),0.2);
      world.addBody(groundBody);
      demo.addVisual(groundBody);
      return world;
    }

  </script>
</body>

</html>